----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    11:50:39 04/12/2011 
-- Design Name: 
-- Module Name:    datapath - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library work;
use work.Definitions.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity datapath is
	 Port ( d_clk              : in STD_LOGIC;	
			  d_clr              : in STD_LOGIC;
			  d_enable           : in STD_LOGIC;
			  instr_word_i       : in STD_LOGIC_VECTOR (17 downto 0);
			  we                 : in STD_LOGIC;
			  d_in               : in STD_LOGIC_VECTOR (9 downto 0);      
			  a_out          		: in STD_LOGIC_VECTOR (2 downto 0);
           flags_in           : in STD_LOGIC_VECTOR (1 downto 0);
           int_req            : in STD_LOGIC;
			  op_code            : in STD_LOGIC_VECTOR(2 downto 0);
			  proc_state	      : in processor_state;
			  is_misc            : in STD_LOGIC;			
	        is_interrupt       : in  STD_LOGIC; 
			  is_branch          : in  STD_LOGIC; 
			  is_reti            : in  STD_LOGIC; 
			  is_ret             : in  STD_LOGIC; 
			  is_jump            : in  STD_LOGIC;
			  inst_addr_o        : out STD_LOGIC_VECTOR (9 downto 0);
			  instr_reg_out      : out STD_LOGIC_VECTOR (17 downto 0);
			  flags_out          :out STD_LOGIC_VECTOR (1 downto 0));
end datapath;

architecture Structural of datapath is
	component ir 
		Port ( ir_clk        : in  STD_LOGIC;
             ir_clr        : in  STD_LOGIC;
             enable_IR     : in  STD_LOGIC;
			    instr_reg_in  : in  STD_LOGIC_VECTOR (17 downto 0);
             instr_reg_out : out STD_LOGIC_VECTOR (17 downto 0));
	end component;
	
	component pc
		Port ( clk      : in  STD_LOGIC;
             pc_reset : in  STD_LOGIC;
             pc_en    : in  STD_LOGIC;
             pc_in    : in  STD_LOGIC_VECTOR (9 downto 0);
             pc_out   : out STD_LOGIC_VECTOR (9 downto 0));
	end component;
	
	component sp 
		Port ( sp_clk    : in  STD_LOGIC;
				 sp_enable : in  STD_LOGIC;
             we        : in  STD_LOGIC; 
             sp_in     : in  STD_LOGIC_VECTOR (2 downto 0); 
             sp_out    : out  STD_LOGIC_VECTOR (2 downto 0)); 
	end component;
	
	component stack
		 Port ( clk_stk : in  STD_LOGIC;
	           we      : in  STD_LOGIC;
			     e_stk   : in  STD_LOGIC;              
			     d_in    : in  STD_LOGIC_VECTOR (9 downto 0);
              a_in    : in  STD_LOGIC_VECTOR (2 downto 0);
			     a_out   : in  STD_LOGIC_VECTOR (2 downto 0);
              d_out   : out STD_LOGIC_VECTOR (9 downto 0));
	end component;
	
	component interrupt_reg
		Port ( clk_i        : in  STD_LOGIC;
             clr_i        : in  STD_LOGIC;
             pc_in        : in  STD_LOGIC_VECTOR (9 downto 0);
             flags_in     : in  STD_LOGIC_VECTOR (1 downto 0);
             int_req      : in  STD_LOGIC;
			    op_code      : in  STD_LOGIC_VECTOR(2 downto 0);
			    proc_state	  : in  processor_state;
			    is_misc      : in  STD_LOGIC;
             pc_out 		  : out STD_LOGIC_VECTOR (9 downto 0);
             flags_out    : out STD_LOGIC_VECTOR (1 downto 0); -- int_ZF, int_CF
             int_enable   : out STD_LOGIC);
	end component;
	
	component mux_sum
		Port ( enable : in  STD_LOGIC;
             instr_reg_out : in  STD_LOGIC_VECTOR (17 downto 0);
             pc_out : in  STD_LOGIC_VECTOR (9 downto 0); 
             s      : out STD_LOGIC_VECTOR (9 downto 0));
	end component;

	component mux_five
		Port ( ret_from_interrupt : in  STD_LOGIC_VECTOR (9 downto 0);
			    ret_from_sub       : in  STD_LOGIC_VECTOR (9 downto 0);
	          is_interrupt       : in  STD_LOGIC; 
			    is_branch          : in  STD_LOGIC; 
			    is_reti            : in  STD_LOGIC; 
			    is_ret             : in  STD_LOGIC; 
			    is_jump            : in  STD_LOGIC; 
			    mux_sum_in         : in  STD_LOGIC_VECTOR (9 downto 0); 
             instr_reg_out      : in  STD_LOGIC_VECTOR (17 downto 0); 
             interrupt          : in  STD_LOGIC; 
             next_pc_adress     : out STD_LOGIC_VECTOR (9 downto 0)); 
	end component;

   signal d_out          : STD_LOGIC_VECTOR (9 downto 0);
	signal mux_1_out		 : STD_LOGIC_VECTOR (9 downto 0);
	signal next_pc_adress : STD_LOGIC_VECTOR (9 downto 0);
	signal pc_in_out	    : STD_LOGIC_VECTOR (9 downto 0);
	signal int_enable     : STD_LOGIC;
	signal sp_out			 : STD_LOGIC_VECTOR (2 downto 0);
	signal pc_out			 : STD_LOGIC_VECTOR(9 downto 0);
	signal i_reg_out		 : STD_LOGIC_VECTOR (17 downto 0);
	
	begin	
		ireg: ir port map (d_clk, d_clr, d_enable, instr_word_i, i_reg_out);		
		intreg: interrupt_reg port map (d_clk, d_clr, pc_out, flags_in, int_req, op_code, proc_state, is_misc, pc_in_out, flags_out, int_enable);
		stk: stack port map (d_clk, we, d_enable, d_in, sp_out, a_out, d_out);
		spointer: sp port map (d_clk, d_enable, we, a_out, sp_out);
		mux_1: mux_sum port map (d_enable, i_reg_out, pc_out, mux_1_out);
		mux_2: mux_five port map (pc_in_out, d_out, is_interrupt, is_branch, is_reti, is_ret, is_jump, mux_1_out, i_reg_out, int_enable, next_pc_adress);
		pcount: pc port map (d_clk, d_clr, d_enable, next_pc_adress, pc_out);
		
		instr_reg_out <= i_reg_out;
		inst_addr_o <= pc_out;
				
end Structural;